home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume11 / mush5.7 / part02 < prev    next >
Encoding:
Internet Message Format  |  1987-09-16  |  49.2 KB

  1. Subject:  v11i052:  Mail user's shell, Part02/12
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rs@uunet.UU.NET
  5.  
  6. Submitted-by: island!argv@Sun.COM (Dan Heller)
  7. Posting-number: Volume 11, Issue 52
  8. Archive-name: mush5.7/Part02
  9.  
  10. #! /bin/sh
  11. # This is a shell archive.  Remove anything before this line, then unpack
  12. # it by saving it into a file and typing "sh file".  To overwrite existing
  13. # files, type "sh file -c".  You can also feed this as standard input via
  14. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  15. # will see the following message at the end:
  16. #        "End of archive 2 (of 12)."
  17. # Contents:  aliases.c curs_io.c dates.c execute.c folders.c
  18. #   main_panel.c rite.c sort.c
  19. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  20. if test -f 'aliases.c' -a "${1}" != "-c" ; then 
  21.   echo shar: Will not clobber existing file \"'aliases.c'\"
  22. else
  23. echo shar: Extracting \"'aliases.c'\" \(4554 characters\)
  24. sed "s/^X//" >'aliases.c' <<'END_OF_FILE'
  25. X/* (c) copyright @(#)aliases.c    2.4    10/15/86 (Dan Heller) */
  26. X
  27. X#include "mush.h"
  28. X
  29. X/*
  30. X * do_alias handles aliases, header settings, functions, and fkeys.
  31. X * since they're all handled in the same manner, the same routine is
  32. X * used. argv[0] determines which to use.
  33. X * alias is given here as an example
  34. X *
  35. X * alias           identify all aliases
  36. X * alias name      identify alias
  37. X * alias name arg1 arg2 arg3... -> name="arg1 arg2 arg3"; call set_option
  38. X * unalias arg1 [arg2 arg3 ... ]        unalias args
  39. X *
  40. X * same is true for dealing with your own headers.
  41. X * (also the expand command)
  42. X * always return -1 since it nas no effect on messages
  43. X */
  44. Xdo_alias(argc, argv)
  45. Xregister char **argv;
  46. X{
  47. X    register char *cmd = *argv, *p;
  48. X    struct options **list;
  49. X    char firstchar = *cmd, buf[BUFSIZ];
  50. X
  51. X    if (argc == 0)
  52. X    return -1;
  53. X    if (firstchar == 'u')
  54. X    firstchar = cmd[2];
  55. X    if (*++argv && !strcmp(*argv, "-?")) { /* doesn't apply for fkeys */
  56. X    register char *help_str;
  57. X    if (firstchar == 'a' || firstchar == 'e')
  58. X        help_str = "alias";
  59. X    else if (firstchar == 'c')
  60. X        help_str = "func_help";
  61. X    else if (firstchar == 'f')
  62. X        help_str = "fkey_help";
  63. X    else
  64. X        help_str = "own_hdrs";
  65. X    return help(0, help_str, cmd_help);
  66. X    }
  67. X
  68. X    if (firstchar == 'a')
  69. X    list = &aliases;
  70. X    else if (firstchar == 'c')
  71. X    list = &functions;
  72. X    else if (firstchar == 'f')
  73. X    list = &fkeys;
  74. X    else
  75. X    list = &own_hdrs;
  76. X
  77. X    if (*cmd == 'u') {
  78. X    if (!*argv)
  79. X        print("%s what?\n", cmd);
  80. X    /* unset a list separated by spaces or ',' */
  81. X    else while (*argv) {
  82. X        if (!strcmp(*argv, "*")) /* unset everything */
  83. X        while (*list)
  84. X            (void) un_set(list, (*list)->option);
  85. X        else if (!un_set(list, *argv))
  86. X        print("\"%s\" isn't set\n", *argv);
  87. X        argv++;
  88. X    }
  89. X    return -1;
  90. X    }
  91. X
  92. X    if (!*argv && *cmd != 'e') {
  93. X    /* just type out all the aliases or own_hdrs */
  94. X    (void) do_set(*list, NULL);
  95. X    return -1;
  96. X    }
  97. X
  98. X    if (*cmd == 'e') {   /* command was "expand" (aliases only) */
  99. X    if (!*argv)
  100. X        print("expand which alias?\n");
  101. X    else
  102. X        do  {
  103. X        print("%s: ", *argv);
  104. X        if (p = alias_to_address(*argv))
  105. X            print("%s\n", p);
  106. X        } while (*++argv);
  107. X    return -1;
  108. X    }
  109. X
  110. X    /* at this point, *argv now points to a variable name ...
  111. X     * check for hdr -- if so, *argv better end with a ':' (check *p)
  112. X     */
  113. X    if (list == &own_hdrs && !(p = index(*argv, ':'))) {
  114. X    print("header labels must end with a ':' (%s)\n", *argv);
  115. X    return -1;
  116. X    }
  117. X    if (!argv[1] && !index(*argv, '='))
  118. X    if (p = do_set(*list, *argv))
  119. X        print("%s\n", p);
  120. X    else
  121. X        print("%s is not set\n", *argv);
  122. X    else {
  123. X    (void) argv_to_string(buf, argv);
  124. X    if ((p = any(buf, " \t=")) && *p != '=')
  125. X        *p = '=';
  126. X    argv[0] = buf;
  127. X    argv[1] = NULL;
  128. X    (void) add_option(list, argv);
  129. X    }
  130. X    return -1;
  131. X}
  132. X
  133. X/* takes string 's' which can be a name or list of names separated by
  134. X * spaces or commas and checks to see if each is aliased to something else.
  135. X * return address of the static buf.
  136. X */
  137. Xchar *
  138. Xalias_to_address(s)
  139. Xregister char *s;
  140. X{
  141. X    static char buf[BUFSIZ];
  142. X    register char *p = s, *p2, *tmp;
  143. X    char newbuf[BUFSIZ];
  144. X    static int recursive;
  145. X
  146. X    if (!aliases)
  147. X    return s;
  148. X    if (!s || !*s) {
  149. X    print("No recipeints!?!\n");
  150. X    return NULL;
  151. X    }
  152. X    skipspaces(0);
  153. X    if (!recursive) {
  154. X    bzero(buf, BUFSIZ);
  155. X    p2 = buf;  /* if we're starting all this, p2 starts at &buf[0] */
  156. X    } else
  157. X    p2 = buf+strlen(buf);   /* else, pick up where we left off */
  158. X
  159. X    if (++recursive == 30) {
  160. X    print("alias references too many addresses!\n");
  161. X    recursive = 0;
  162. X    return NULL;
  163. X    }
  164. X    /* find a comma, space, or newline -- if none exists, still go thru once */
  165. X    for (s = p; (p = any(s, ", \n")) || *s; s = p) {
  166. X    if (p)
  167. X        *p++ = 0;  /* null terminate, comma/space/newline was found */
  168. X    else
  169. X        for(p = s; *p; p++);   /* last in list; go to end of string */
  170. X
  171. X    /* if this is an alias, recurse this routine to expand it out */
  172. X    if ((tmp = do_set(aliases, s)) && *tmp) {
  173. X        if (!alias_to_address(strcpy(newbuf, tmp)))
  174. X        return NULL;
  175. X        else
  176. X        p2 = buf+strlen(buf);
  177. X    /* Now, make sure the buffer doesn't overflow */
  178. X    } else if (strlen(s) + (p2-buf) + 2 > BUFSIZ) {  /* add " "  + NULL */
  179. X        print("address length too long.\n");
  180. X        recursive = 0;
  181. X        return NULL;
  182. X    } else {
  183. X        /* append the new alias (or unchanged address) onto the buffer */
  184. X        p2 += Strcpy(p2, s);
  185. X        p2 += Strcpy(p2, ", "); /* two Strcpy's is faster than sprintf */
  186. X    }
  187. X    skipspaces(0);
  188. X    }
  189. X    if (recursive)
  190. X    recursive--;
  191. X    if (!recursive)
  192. X    *(p2-2) = 0;  /* get rid of last ", " if end of recursion */
  193. X    return buf;
  194. X}
  195. END_OF_FILE
  196. if test 4554 -ne `wc -c <'aliases.c'`; then
  197.     echo shar: \"'aliases.c'\" unpacked with wrong size!
  198. fi
  199. # end of 'aliases.c'
  200. fi
  201. if test -f 'curs_io.c' -a "${1}" != "-c" ; then 
  202.   echo shar: Will not clobber existing file \"'curs_io.c'\"
  203. else
  204. echo shar: Extracting \"'curs_io.c'\" \(5704 characters\)
  205. sed "s/^X//" >'curs_io.c' <<'END_OF_FILE'
  206. X/* @(#)curs_io.c    (c) copyright 3/18/87 (Dan Heller) */
  207. X
  208. X/* curs_io.c -- curses based I/O */
  209. X#include "mush.h"
  210. X
  211. X#ifdef CURSES
  212. X#include "bindings.h"
  213. X#endif CURSES
  214. X
  215. X#ifdef Addch
  216. X#undef Addch
  217. X#endif Addch
  218. X
  219. X#ifndef CURSES
  220. X
  221. X#define Addch(c) if (isoff(glob_flags, ECHO_FLAG)) \
  222. X              fputc(c, stdout), fflush(stdout)
  223. X
  224. X#else
  225. X
  226. X/* see end of Getstr */
  227. X#define Addch(c)  \
  228. X    if (iscurses) \
  229. X    addch(c), refresh(); \
  230. X    else if (isoff(glob_flags, ECHO_FLAG)) \
  231. X    fputc(c, stdout), fflush(stdout)
  232. X#endif CURSES
  233. X
  234. X/*
  235. X * get a string of at most 'length' chars.
  236. X * allow backspace-space-backspace, kill word and kill line
  237. X * (options set by user in stty).
  238. X * length is the max length this string can get. offset is from beginning
  239. X * of string.
  240. X * input of ^D returns -1; otherwise, return the number of chars in string.
  241. X */
  242. X#define backspace()     { Addch('\b'); Addch(' '); Addch('\b'); }
  243. X
  244. XGetstr(String, length, offset)
  245. Xchar String[];
  246. Xregister int length;
  247. X{
  248. X    register int c;
  249. X    register int count = offset;
  250. X
  251. X    while ((c = getchar()) != '\n' && c != 4 /* ^D */ && c != EOF &&
  252. X    isoff(glob_flags, WAS_INTR)) {
  253. X    /* echo isn't set, so whatever the character, enter it */
  254. X    if (ison(glob_flags, ECHO_FLAG) && count < length)
  255. X        String[count++] = c;
  256. X    else if (c == _tty.sg_erase || c == 8 || c == 127) {
  257. X        if (count) {
  258. X        backspace() /* macro */
  259. X        count--;
  260. X        } else if (!count && iscurses) {
  261. X        String[0] = '\0';
  262. X        return -1;
  263. X        }
  264. X    } else if (c == _tty.sg_kill) {
  265. X        if (count) {
  266. X        do
  267. X            backspace()  /* macro */
  268. X        while (--count);
  269. X        }
  270. X    } else
  271. X#ifndef TIOCGLTC
  272. X    if (c == '\022') /* system doesn't have ltchars */
  273. X#else
  274. X    if (c == ltchars.t_rprntc) /* reprint line */
  275. X#endif TIOCGLTC
  276. X        String[count] = 0, printf("\n%s", String);
  277. X        else
  278. X#ifndef TIOCGLTC
  279. X    if (c == '\027') /* system doesn't have ltchars */
  280. X#else
  281. X    if (c == ltchars.t_werasc) /* word erase */
  282. X#endif TIOCGLTC
  283. X        while (count) {
  284. X        backspace();
  285. X        String[count--] = 0;
  286. X        if (!count || (String[count-1]== ' '&& !isspace(String[count])))
  287. X            break;
  288. X        }
  289. X    else if (c == '\t')
  290. X        do  {
  291. X        Addch(' ');
  292. X        String[count] = ' ';
  293. X        } while (++count % 8 && count < length);
  294. X    else if (count == length)
  295. X        bell();
  296. X    else if (c > 31 && c != 127) {
  297. X        Addch(c);
  298. X        String[count++] = c;
  299. X    }
  300. X    }
  301. X    if (c == 4 || c == EOF || ison(glob_flags, WAS_INTR)) {     /* ^D */
  302. X    if (feof(stdin))
  303. X        clearerr(stdin);
  304. X    return -1;
  305. X    }
  306. X    if (count && String[count-1] == '\\') {
  307. X    int count2;
  308. X    if (isoff(glob_flags, ECHO_FLAG))
  309. X        putchar('\n');
  310. X    if ((count2 = Getstr(&String[count-1], length - count + 1, 0)) == -1)
  311. X        return -1;
  312. X    return count + count2;
  313. X    }
  314. X    if (!iscurses && isoff(glob_flags, ECHO_FLAG))
  315. X    putchar('\n');
  316. X    while (count > 0 && isspace(String[count-1]))
  317. X    --count;
  318. X    String[count] = 0;
  319. X    return count;
  320. X}
  321. X
  322. X#undef backspace
  323. X#undef Addch
  324. X
  325. X#ifdef CURSES
  326. X/* curses based "more" like option */
  327. Xvoid
  328. Xc_more()
  329. X{
  330. X    register char c;
  331. X
  332. X    print_more("--more--");
  333. X    while ((c = getchar()) != ' ' && c != '\n')
  334. X    bell();
  335. X    if (!iscurses && c != '\n')
  336. X    while (getchar() != '\n');
  337. X}
  338. X
  339. X/*
  340. X * prompt for a carriage return, but return whatever user types unless
  341. X * it's a character which he might regret (like 'q' or 'x'). Ignore
  342. X * interrupts (kind of) because we have nowhere to longjmp to.  When we
  343. X * return, we'll setjmp again (top of loop.c)
  344. X */
  345. Xhit_return()
  346. X{
  347. X    int c;
  348. X
  349. X    turnon(glob_flags, IGN_SIGS);
  350. X    iscurses = FALSE;
  351. X    (void) check_new_mail();
  352. X    iscurses = TRUE;
  353. X    mail_status(1), addstr("...continue... "), refresh();
  354. X    c = getcmd();
  355. X    turnoff(glob_flags, IGN_SIGS);
  356. X
  357. X    /* don't let the user type something he might regret */
  358. X    if (c == C_QUIT || c == C_EXIT)
  359. X    return 0;
  360. X    return c;
  361. X}
  362. X
  363. Xcurses_msg_list(str, list, m_list)
  364. Xregister char *str, *list;
  365. Xchar m_list[];
  366. X{
  367. X    register char *p = NULL;
  368. X
  369. X    print(str);
  370. X    if (Getstr(list, COLS-13, 0) <= 0 || !(p = do_range(list, m_list)) ||
  371. X    (p == list && *p && *p != '$' && *p != '^')) {
  372. X    if (p)
  373. X        print("Invalid message list: %s", p);
  374. X    return 0;
  375. X    }
  376. X    move(LINES-1, 0), refresh();
  377. X    return 1;
  378. X}
  379. X
  380. Xcurs_vars(which, cntd_cmd)
  381. Xint which;  /* really, a char */
  382. Xint *cntd_cmd;
  383. X{
  384. X    char c, buf[128], buf2[128], *string;
  385. X    struct options **list;
  386. X
  387. X    switch(which) {
  388. X    case C_OWN_HDR : string = "own_hdrs", list = &own_hdrs;
  389. X    when C_ALIAS : string = "alias", list = &aliases;
  390. X    when C_IGNORE : string = "ignore", list = &ignore_hdr;
  391. X    when C_VAR_SET : string = "set", list = &set_options;
  392. X    otherwise : clr_bot_line(); return;
  393. X    }
  394. X
  395. X    print("%s [? Set Unset All]: ", string);
  396. X    c = getchar();
  397. X    clr_bot_line();
  398. X    switch (Lower(c)) {
  399. X    /* if help, print help -- if "all", show all settings. */
  400. X    case '?' : case 'a' :
  401. X        if (c == '?') {
  402. X        if (!strcmp(string, "set")) {
  403. X            print("which variable? [All <var>]: ");
  404. X            if ((c = Getstr(buf, COLS-40, 0)) < 0)
  405. X            return;
  406. X            clr_bot_line();
  407. X            if (c > 0) {
  408. X            Lower(*buf);
  409. X            if (!strcmp(buf, "a"))
  410. X                (void) strcpy(buf, "all");
  411. X            if (!strcmp(buf, "all"))
  412. X                *cntd_cmd = 1;
  413. X            (void) cmd_line(sprintf(buf2, "set ?%s", buf),msg_list);
  414. X            return;
  415. X            }
  416. X        }
  417. X        /* help returns next command (hit_return) */
  418. X        help(0, string, cmd_help);
  419. X        *cntd_cmd = 1;
  420. X        return;
  421. X        }
  422. X        *cntd_cmd = 1;
  423. X        do_set(*list, NULL);
  424. X
  425. X    /* if set, prompt for string and let user type */
  426. X    when 's' :
  427. X        print("set: ");
  428. X        c = Getstr(buf, COLS-18, 0);
  429. X        clr_bot_line();
  430. X        if (c > 0)
  431. X        (void) cmd_line(sprintf(buf2, "%s %s", string, buf), msg_list);
  432. X
  433. X    /* if unset, just as easy as set! */
  434. X    when 'u' :
  435. X        print("unset: ", string);
  436. X        if (Getstr(buf, COLS-18, 0) > 0 && !un_set(list, buf)) {
  437. X        print("%s isn't set", buf);
  438. X        if (*cntd_cmd)
  439. X            putchar('\n');
  440. X        }
  441. X    }
  442. X}
  443. X
  444. X#endif CURSES
  445. END_OF_FILE
  446. if test 5704 -ne `wc -c <'curs_io.c'`; then
  447.     echo shar: \"'curs_io.c'\" unpacked with wrong size!
  448. fi
  449. # end of 'curs_io.c'
  450. fi
  451. if test -f 'dates.c' -a "${1}" != "-c" ; then 
  452.   echo shar: Will not clobber existing file \"'dates.c'\"
  453. else
  454. echo shar: Extracting \"'dates.c'\" \(6037 characters\)
  455. sed "s/^X//" >'dates.c' <<'END_OF_FILE'
  456. X/* @(#)dates.c    1.1    (c) copyright 10/15/86 (Dan Heller) */
  457. X
  458. X#include "mush.h"
  459. X
  460. Xchar *day_names[] = {
  461. X    "Sun", "Mon", "Tues", "Wed", "Thurs", "Fri", "Sat"
  462. X};
  463. Xchar *month_names[] = {     /* imported in pick.c */
  464. X    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  465. X    "July", "Aug", "Sep", "Oct", "Nov", "Dec"
  466. X};
  467. X
  468. X/* Time() returns a string according to criteria:
  469. X *   if "now" is 0, then the current time is gotten and used.
  470. X *       else, use the time described by now
  471. X *   opts points to a string of args which is parsed until an unknown
  472. X *       arg is found and opts will point to that upon return.
  473. X *   valid args are T (time of day), D (day of week), M (month), Y (year),
  474. X *       N (number of day in month -- couldn't think of a better letter).
  475. X */
  476. Xchar *
  477. XTime(opts, now)
  478. Xregister char *opts;
  479. Xlong now;
  480. X{
  481. X    static char time_buf[30];
  482. X    struct tm       *T;
  483. X    register char *p = time_buf;
  484. X    long      x;
  485. X
  486. X    if (!opts)
  487. X    return NULL;
  488. X    if (now)
  489. X    x = now;
  490. X    else
  491. X    (void) time(&x);
  492. X    T = localtime(&x);
  493. X    for (;; opts++) {
  494. X    switch(*opts) {
  495. X        case 'T': (void) sprintf(p, "%d:%02d", (T->tm_hour) ?
  496. X              ((T->tm_hour <= 12) ? T->tm_hour : T->tm_hour - 12) : 12,
  497. X              T->tm_min);
  498. X        when 'D': (void) strcpy(p, day_names[T->tm_wday]);
  499. X        when 'M': (void) strcpy(p, month_names[T->tm_mon]);
  500. X        when 'Y': (void) sprintf(p, "%d", T->tm_year);
  501. X        when 'N': (void) sprintf(p, "%d", T->tm_mday);
  502. X        otherwise: *--p = 0; return time_buf;
  503. X    }
  504. X    p += strlen(p);
  505. X    *p++ = ' ';
  506. X    }
  507. X}
  508. X
  509. X/* find the date of a message and return a string of the same form
  510. X * described by parse_date() below.
  511. X */
  512. Xchar *
  513. Xmsg_date(n)
  514. Xregister int n;
  515. X{
  516. X    register char *p, *p2 = NULL;
  517. X    char line[256];
  518. X
  519. X    /* not in use */
  520. X    /* try the easy way out first -- This is potentially a serious kludge
  521. X     * because not all message-id lines are right. -- most of the time,
  522. X     * this is correct.  it's not correct from messages from strange
  523. X     * mailers (non-sendmail) they do a different format in message-id.
  524. X    if ((p = header_field(n, "message-id")) && (p2 = index(p, '<'))) {
  525. X    p = p2+1;
  526. X    if (p2 = index(p, '.')) {
  527. X        *p2 = 0;
  528. X        return p;
  529. X    }
  530. X    }
  531. X     */
  532. X
  533. X    /* else, get the "date" line, if that fails, get the date in "From" line */
  534. X    if ((p = header_field(n, "date")) && (p2 = parse_date(p)))
  535. X    return p2;
  536. X
  537. X    (void) fseek(tmpf, msg[n].m_offset, L_SET);
  538. X    (void) fgets(line, BUFSIZ, tmpf);
  539. X    if (!(p = index(line, ' ')) || !(p2 = index(p+1, ' ')))
  540. X    return NULL;
  541. X    p = p2;
  542. X
  543. X    if (!(p2 = parse_date(p)))
  544. X    print("Message %d has bad date: %s\n", n+1, p);
  545. X    return p2;
  546. X}
  547. X
  548. X/* parse date and return a string that looks like
  549. X *    "%2d%2d%2d%2d%2d", yr,mo,date,hrs,mins
  550. X */
  551. Xchar *
  552. Xparse_date(p)
  553. Xregister char *p;
  554. X{
  555. X    static char buf[11];
  556. X    int Month = 0, Day = 0, Year = 0, Hours = -1, Mins = -1;
  557. X
  558. X    skipspaces(0);
  559. X
  560. X    /* Possible combinations that we could have:
  561. X     *   day_number month_name year_number time timezone ...
  562. X     *   day_name month_name day_number time year_number
  563. X     *   day_name month_name day_number year_number time
  564. X     *   day_name day_number month_name year_number time
  565. X     *   day_number month_name year_number time
  566. X     *   day_number month_name year_number time-timezone (day)
  567. X     *                                       ^no colon separator
  568. X     *   day_name month_name day_number time timezone year_number
  569. X     *   day_number-month_name-year time
  570. X     *   day_name, day_number-month_name-year time
  571. X     */
  572. X    if (sscanf(p, "%d %s %2d %d:%d", &Day,buf,&Year,&Hours,&Mins) == 5
  573. X    ||
  574. X    sscanf(p, "%*s %s %d %d:%d:%*d %d", buf,&Day,&Hours,&Mins,&Year) == 5
  575. X    ||
  576. X    sscanf(p, "%*s %s %d %d %d:%d", buf,&Day,&Year,&Hours,&Mins) == 5
  577. X    ||
  578. X    sscanf(p, "%*s %d %s %d %d:%d", &Day,buf,&Year,&Hours,&Mins) == 5
  579. X    ||
  580. X    sscanf(p, "%d %s %d %d:%d", &Day,buf,&Year,&Hours,&Mins) == 5
  581. X    ||
  582. X    sscanf(p, "%d %s %d %2d%2d", &Day,buf,&Year,&Hours,&Mins) == 5
  583. X    ||
  584. X    sscanf(p, "%*s %s %d %d:%d:%*d %*s %d", 
  585. X                    buf, &Day, &Hours, &Mins, &Year) == 5
  586. X    ||
  587. X    sscanf(p,"%d-%[^-]-%d %d:%d", &Day, buf, &Year, &Hours, &Mins) == 5
  588. X    ||
  589. X    sscanf(p,"%*s %d-%[^-]-%d %d:%d", &Day, buf, &Year, &Hours, &Mins) == 5) {
  590. X    if (Year > 1900)
  591. X        Year -= 1900;
  592. X    if ((Month = month_to_n(buf)) == -1) {
  593. X        print("bad month: %s\n", p);
  594. X        return NULL;
  595. X    }
  596. X    return sprintf(buf, "%02d%02d%02d%02d%02d", Year,Month,Day,Hours,Mins);
  597. X    }
  598. X    print("Unknown date format: %s\n", p);
  599. X    return NULL;
  600. X}
  601. X
  602. X/* pass a string in the form described above, put into string. "yr" is
  603. X * not used, but is here anyway in case you want to modify it to use it.
  604. X */
  605. Xchar *
  606. Xdate_to_string(Date)
  607. Xchar *Date;
  608. X{
  609. X    static char buf[30];
  610. X    int yr, mon, day, hr, mins;
  611. X    char a_or_p, *p = buf;
  612. X
  613. X    (void) sscanf(Date, "%2d%2d%2d%2d%02d", &yr, &mon, &day, &hr, &mins);
  614. X    a_or_p = (hr < 12)? 'a': 'p';
  615. X    p += strlen(sprintf(p, "%s %2.d, ", month_names[mon-1], day));
  616. X    (void) sprintf(p, "%2.d:%02d%cm",
  617. X      (hr)? (hr <= 12)? hr: hr - 12: 12, mins, a_or_p);
  618. X    return buf;
  619. X}
  620. X
  621. X#define JAN    1
  622. X#define FEB    2
  623. X#define MAR    3
  624. X#define APR    4
  625. X#define MAY    5
  626. X#define JUN    6
  627. X#define JUL    7
  628. X#define AUG    8
  629. X#define SEP    9
  630. X#define OCT    10
  631. X#define NOV    11
  632. X#define DEC    12
  633. X
  634. X/* stolen direct from ELM */
  635. Xmonth_to_n(name)
  636. Xregister char *name;
  637. X{
  638. X    /** return the month number given the month name... **/
  639. X
  640. X    register char ch;
  641. X
  642. X    switch (lower(*name)) {
  643. X    case 'a' : if ((ch = lower(name[1])) == 'p')
  644. X               return(APR);
  645. X           else if (ch == 'u')
  646. X               return(AUG);
  647. X           else return(-1);    /* error! */
  648. X    case 'd' : return(DEC);
  649. X    case 'f' : return(FEB);
  650. X    case 'j' : if ((ch = lower(name[1])) == 'a')
  651. X               return(JAN);
  652. X           else if (ch == 'u') {
  653. X             if ((ch = lower(name[2])) == 'n')
  654. X             return(JUN);
  655. X             else if (ch == 'l')
  656. X             return(JUL);
  657. X             else return(-1);        /* error! */
  658. X           }
  659. X           else return(-1);        /* error */
  660. X    case 'm' : if ((ch = lower(name[2])) == 'r')
  661. X               return(MAR);
  662. X           else if (ch == 'y')
  663. X               return(MAY);
  664. X           else return(-1);        /* error! */
  665. X    case 'n' : return(NOV);
  666. X    case 'o' : return(OCT);
  667. X    case 's' : return(SEP);
  668. X    default  : return(-1);
  669. X    }
  670. X}
  671. END_OF_FILE
  672. if test 6037 -ne `wc -c <'dates.c'`; then
  673.     echo shar: \"'dates.c'\" unpacked with wrong size!
  674. fi
  675. # end of 'dates.c'
  676. fi
  677. if test -f 'execute.c' -a "${1}" != "-c" ; then 
  678.   echo shar: Will not clobber existing file \"'execute.c'\"
  679. else
  680. echo shar: Extracting \"'execute.c'\" \(4414 characters\)
  681. sed "s/^X//" >'execute.c' <<'END_OF_FILE'
  682. X/* execute.c     (c) copyright    10/28/86 (Dan Heller) */
  683. X
  684. X#include "mush.h"
  685. X#ifdef BSD
  686. X#include <sys/wait.h>
  687. X#else
  688. X#ifndef SYSV
  689. X#include <wait.h>
  690. X#endif SYSV
  691. X#endif BSD
  692. X
  693. X#ifdef lint
  694. X#include <sys/resource.h>
  695. X#endif lint
  696. X
  697. Xexecute(argv)
  698. Xchar **argv;
  699. X{
  700. X#ifdef SYSV
  701. X    int status;
  702. X#else
  703. X    union wait status;
  704. X#endif SYSV
  705. X#ifdef SIGCONT
  706. X    int    (*oldstop)(), (*oldcont)();
  707. X#endif SIGCONT
  708. X    int pid, (*oldint)(), (*oldquit)();
  709. X
  710. X#ifdef SUNTOOL
  711. X    if (istool) {
  712. X    print("Editing letter...");
  713. X
  714. X    panel_set(abort_item, PANEL_SHOW_ITEM, FALSE, 0);
  715. X    panel_set(send_item,  PANEL_SHOW_ITEM, FALSE, 0);
  716. X    panel_set(edit_item,  PANEL_SHOW_ITEM, FALSE, 0);
  717. X    win_setrect(tty_sw->ts_windowfd, &msg_rect);
  718. X    msg_rect.r_height = 0;
  719. X    win_setrect(msg_sw->ts_windowfd, &msg_rect);
  720. X    if ((exec_pid = ttysw_fork(tty_sw->ts_data, argv,
  721. X        &tty_sw->ts_io.tio_inputmask,
  722. X        &tty_sw->ts_io.tio_outputmask,
  723. X        &tty_sw->ts_io.tio_exceptmask)) == -1)
  724. X        error("%s failed", *argv), sigchldcatcher();
  725. X    Debug("tty pid = %d\n", exec_pid);
  726. X    return;
  727. X    }
  728. X#endif SUNTOOL
  729. X    oldint = signal(SIGINT, SIG_IGN);
  730. X    oldquit = signal(SIGQUIT, SIG_IGN);
  731. X#ifdef SIGCONT
  732. X    oldstop = signal(SIGTSTP, SIG_DFL);
  733. X    oldcont = signal(SIGCONT, SIG_DFL);
  734. X#endif SIGCONT
  735. X    turnon(glob_flags, IGN_SIGS);
  736. X
  737. X    echo_on();
  738. X    if ((exec_pid = vfork()) == 0) {
  739. X    (void) signal(SIGINT, SIG_DFL);
  740. X    (void) signal(SIGQUIT, SIG_DFL);
  741. X    execvp(*argv, argv);
  742. X    if (errno == ENOENT)
  743. X        print("%s: command not found.\n", *argv);
  744. X    else
  745. X        error(*argv);
  746. X    _exit(-1);
  747. X    }
  748. X    /* parent's got to do something; sigchldcatcher will do waiting
  749. X     * if other forks die (sendmail), then this wait will catch them,
  750. X     * This loop will really get -1, cuz sigchldcatcher will catch all else.
  751. X     */
  752. X    while ((pid = wait(&status) != -1) && pid != exec_pid)
  753. X    Debug("The exec loop caught a signal? (pid = %d)\n", pid);
  754. X    /* reset our ttymodes */
  755. X    echo_off();
  756. X    (void) signal(SIGINT, oldint);
  757. X    (void) signal(SIGQUIT, oldquit);
  758. X#ifdef SIGCONT
  759. X    (void) signal(SIGTSTP, oldstop);
  760. X    (void) signal(SIGCONT, oldcont);
  761. X#endif SIGCONT
  762. X    turnoff(glob_flags, IGN_SIGS);
  763. X}
  764. X
  765. Xsigchldcatcher()
  766. X{
  767. X#ifdef SUNTOOL
  768. X    struct rect rect;
  769. X#endif SUNTOOL
  770. X#ifdef SYSV
  771. X    int status;
  772. X#else
  773. X    union wait status;
  774. X#endif SYSV
  775. X    int       pid;
  776. X
  777. X#ifdef BSD
  778. X    /* The follwoing SHOULDN'T be necessary, but it is!!! ttysw_fork()
  779. X     * returns the pid of the thing that it executes, but that's not the
  780. X     * pid that dies!  There are many procs that might die from ttysw_fork
  781. X     * one of them is the process, another is the tty, etc... other
  782. X     * procs that might die are sendmail, fortune, etc... tool_sigchld()
  783. X     * handles these, but we can't let it have control unless we KNOW the
  784. X     * editor is done.
  785. X     * so if what we catch is not the exec_pid from ttysw_fork(), then
  786. X     * send ourselves a sigchld to go thru this routine again.  mush -d
  787. X     */
  788. X    while ((pid = wait3(&status, WNOHANG, (struct rusage *)0)) > 0) {
  789. X    Debug("%d died...\n", pid);
  790. X    if (pid == exec_pid)
  791. X        break;
  792. X    }
  793. X#else
  794. X#ifndef SYSV
  795. X    while ((pid = wait2(&status, WNOHANG)) > 0 && pid != exec_pid)
  796. X    Debug("%d died...\n", pid);
  797. X#else SYSV
  798. X    while ((pid = wait((int *)0)) > 0 && pid != exec_pid)
  799. X    Debug("%d died...\n", pid);
  800. X#endif SYSV
  801. X#endif BSD
  802. X#ifndef SUNTOOL
  803. X    }
  804. X#else SUNTOOL
  805. X    if (pid != exec_pid || exec_pid <= 0) /* if the editor didn't die, return */
  806. X    return;
  807. X    /* editor died -- reset exec_pid so no one thinks we're running */
  808. X    exec_pid = 0;
  809. X    /* only the tool needs to continue from here.  Reset the win */
  810. X    if (istool < 1)
  811. X    return;
  812. X    tool_sigchld(tool);
  813. X    print("Editor done");
  814. X    win_getrect(tty_sw->ts_windowfd, &msg_rect);
  815. X    if (!msg_rect.r_height) {
  816. X    print_more(" (well, something just happened)");
  817. X    return;
  818. X    }
  819. X    rect.r_top = rect.r_left = rect.r_height = 0;
  820. X    rect.r_width = msg_rect.r_width;
  821. X    win_setrect(tty_sw->ts_windowfd, &rect);
  822. X    win_setrect(msg_sw->ts_windowfd, &msg_rect);
  823. X    panel_set(comp_item, PANEL_SHOW_ITEM, FALSE, 0);
  824. X    panel_set(send_item, PANEL_SHOW_ITEM, TRUE, 0);
  825. X    panel_set(edit_item, PANEL_SHOW_ITEM, TRUE, 0);
  826. X    panel_set(abort_item, PANEL_SHOW_ITEM, TRUE, 0);
  827. X    wprint("(continue editing letter.)\n");
  828. X    pw_char(msg_win, txt.x,txt.y, PIX_SRC, fonts[curfont], '_');
  829. X}
  830. X
  831. Xsigtermcatcher()
  832. X{
  833. X    ttysw_done(tty_sw->ts_data);
  834. X    if (ison(glob_flags, IS_GETTING))
  835. X    rm_edfile(-1);
  836. X    cleanup(SIGTERM);
  837. X}
  838. X#endif SUNTOOL
  839. END_OF_FILE
  840. if test 4414 -ne `wc -c <'execute.c'`; then
  841.     echo shar: \"'execute.c'\" unpacked with wrong size!
  842. fi
  843. # end of 'execute.c'
  844. fi
  845. if test -f 'folders.c' -a "${1}" != "-c" ; then 
  846.   echo shar: Will not clobber existing file \"'folders.c'\"
  847. else
  848. echo shar: Extracting \"'folders.c'\" \(4933 characters\)
  849. sed "s/^X//" >'folders.c' <<'END_OF_FILE'
  850. X/* @(#)folders.c    (c) copyright 10/18/86 (Dan Heller) */
  851. X
  852. X#include "mush.h"
  853. X
  854. X/* folder %[user]  --new mailfile is the spool/mail/login file [user].
  855. X * folder #  --new mailfile is the folder previous to the current folder
  856. X * folder &  --new mailfile is ~/mbox (or whatever "mbox" is set to)
  857. X * folder +file --new mailfile is in the directory "folder"; name is 'file'
  858. X * folder "path" --full path name or the one in current working directory.
  859. X *
  860. X * in all cases, changes are updated unless a '!' is specified after the
  861. X * folder command (e.g. "f!", "folder !" "fo!" .. all permutations)
  862. X * as usual, if new mail has arrived before the file is copied back, then
  863. X * user will be notified beforehand.
  864. X *
  865. X * RETURN -1 on error -- else return 0. All bits in msg_list are set to true.
  866. X */
  867. Xfolder(argc, argv, list)
  868. Xregister char **argv, list[];
  869. X{
  870. X    int n, updating = !strcmp(*argv, "update"), do_read_only = 0, no_hdrs = 0;
  871. X    static char oldfolder[256];
  872. X    char *tmp, *newfolder = NULL, buf[256];
  873. X
  874. X    if (ison(glob_flags, DO_PIPE)) {
  875. X    print("You can't pipe to the folder command");
  876. X    return -1;
  877. X    }
  878. X    while (*++argv && (**argv == '-' || **argv == '!'))
  879. X    if (!strcmp(*argv, "-?"))
  880. X        return help(0, "folder_help", cmd_help);
  881. X    else if (!strcmp(*argv, "-N"))
  882. X        no_hdrs = 1;
  883. X    else if (!strcmp(*argv, "-r"))
  884. X        do_read_only = 1;
  885. X    else if (!strcmp(*argv, "!"))
  886. X        turnoff(glob_flags, DO_UPDATE);
  887. X
  888. X    if (updating)
  889. X    (void) strcpy(buf, mailfile);
  890. X    else {
  891. X    if (!*argv) {
  892. X        print("%s\n", mailfile);
  893. X        return 0;
  894. X    }
  895. X    if (!strcmp(*argv, "#"))
  896. X        if (!*oldfolder) {
  897. X        print("No previous folder\n");
  898. X        return -1;
  899. X        } else
  900. X        newfolder = oldfolder;
  901. X    else if (!strcmp(*argv, "&")) {
  902. X        if (!(newfolder = do_set(set_options, "mbox")) || !*newfolder)
  903. X        newfolder = DEF_MBOX;
  904. X    } else
  905. X        newfolder = *argv;
  906. X    n = 0;
  907. X    tmp = getpath(newfolder, &n);
  908. X    if (n == -1) {
  909. X        print("%s: %s\n", newfolder, tmp);
  910. X        return -1;
  911. X    } else if (n == 1) {
  912. X        print("%s: is a directory\n", tmp);
  913. X        return -1;
  914. X    }
  915. X    /* strcpy so copyback() below (which calls getpath) doesn't change
  916. X     * the data that tmp intended to point to.
  917. X     */
  918. X    (void) strcpy(buf, tmp);
  919. X    }
  920. X    if (access(buf, R_OK)) {
  921. X    error("Can't open %s", buf);
  922. X    return -1;
  923. X    }
  924. X    if (access(buf, W_OK))
  925. X    do_read_only = 1;
  926. X#ifdef SUNTOOL
  927. X    if (istool) lock_cursors();
  928. X#endif SUNTOOL
  929. X    if (ison(glob_flags, DO_UPDATE) && !copyback()) {
  930. X#ifdef SUNTOOL
  931. X    if (istool) unlock_cursors();
  932. X#endif SUNTOOL
  933. X    /* could be an error, but new mail probably came in */
  934. X    return -1;
  935. X    }
  936. X    (void) strcpy(oldfolder, mailfile);
  937. X    strdup(mailfile, buf);
  938. X    do_read_only? turnon(glob_flags,READ_ONLY) : turnoff(glob_flags,READ_ONLY);
  939. X    last_size = spool_size = 0L;
  940. X    msg_cnt = 0;
  941. X    turnoff(glob_flags, CONT_PRNT);
  942. X
  943. X    turnon(glob_flags, IGN_SIGS);
  944. X    /* clear the tempfile */
  945. X    fclose(tmpf);
  946. X    if (!(tmpf = fopen(tempfile, "w"))) {
  947. X    error("error truncating %s", tempfile);
  948. X    turnoff(glob_flags, IGN_SIGS);
  949. X    return -1;
  950. X    }
  951. X    getmail();
  952. X    last_msg_cnt = msg_cnt;  /* for check_new_mail */
  953. X    (void) mail_size();
  954. X#ifdef SUNTOOL
  955. X    if (istool) {
  956. X    panel_set(next_scr, PANEL_SHOW_ITEM, FALSE, 0);
  957. X    panel_set(prev_scr, PANEL_SHOW_ITEM, FALSE, 0);
  958. X    pw_rop(hdr_win, 0,0, hdr_rect.r_width, hdr_rect.r_height,PIX_CLR,0,0,0);
  959. X    }
  960. X#endif SUNTOOL
  961. X    current_msg = 0;
  962. X    turnoff(glob_flags, IGN_SIGS);
  963. X
  964. X    /* now sort messages according a user_defined default */
  965. X    if (!updating && msg_cnt > 1 && is_spool(mailfile) &&
  966. X        (tmp = do_set(set_options, "sort"))) {
  967. X    (void) sprintf(buf, "sort %s", tmp);
  968. X    if (argv = make_command(buf, TRPL_NULL, &argc)) {
  969. X        /* msg_list can't be null for do_command and since we're not
  970. X         * interested in the result, call sort directly
  971. X         */
  972. X        (void) sort(argc, argv, NULL);
  973. X        free_vec(argv);
  974. X    }
  975. X    }
  976. X    turnoff(glob_flags, DO_UPDATE);
  977. X
  978. X    while (current_msg < msg_cnt && isoff(msg[current_msg].m_flags, UNREAD))
  979. X    current_msg++;
  980. X    if (current_msg == msg_cnt)
  981. X    current_msg = 0;
  982. X
  983. X    if (!istool && !iscurses)
  984. X    mail_status(0);
  985. X    /* be quite if we're piping */
  986. X    if ((istool || !updating) && isoff(glob_flags, IS_PIPE) &&
  987. X    (istool || !no_hdrs) && msg_cnt)
  988. X    (void) cmd_line(sprintf(buf, "headers %d", current_msg+1), msg_list);
  989. X#ifdef SUNTOOL
  990. X    if (istool) {
  991. X    if (!msg_cnt)
  992. X        print("No Mail in %s\n", mailfile);
  993. X    else if (isoff(glob_flags, IS_GETTING) && !getting_opts)
  994. X        display_msg(current_msg, (long)0);
  995. X    unlock_cursors();
  996. X    }
  997. X#endif SUNTOOL
  998. X    if (list) {
  999. X    clear_msg_list(list);
  1000. X    bitput(list, list, msg_cnt, =~) /* macro */
  1001. X    }
  1002. X    return 0;
  1003. X}
  1004. X
  1005. Xfolders(argc, argv)
  1006. Xregister char **argv;
  1007. X{
  1008. X    register char *p;
  1009. X    char buf[128], unused[MAXMSGS_BITS];
  1010. X
  1011. X    if (!(p = do_set(set_options, "folder")) || !*p) {
  1012. X    print("You have no folder variable set.\n");
  1013. X    return -1;
  1014. X    }
  1015. X    (void) sprintf(buf, "ls %s", p);
  1016. X    if (argv = make_command(buf, TRPL_NULL, &argc))
  1017. X    (void) do_command(argc, argv, unused);
  1018. X    return -1;
  1019. X}
  1020. END_OF_FILE
  1021. if test 4933 -ne `wc -c <'folders.c'`; then
  1022.     echo shar: \"'folders.c'\" unpacked with wrong size!
  1023. fi
  1024. # end of 'folders.c'
  1025. fi
  1026. if test -f 'main_panel.c' -a "${1}" != "-c" ; then 
  1027.   echo shar: Will not clobber existing file \"'main_panel.c'\"
  1028. else
  1029. echo shar: Extracting \"'main_panel.c'\" \(9355 characters\)
  1030. sed "s/^X//" >'main_panel.c' <<'END_OF_FILE'
  1031. X/* "@(#)main_panel.c    (c) copyright    10/18/86 (Dan Heller) */
  1032. X
  1033. X#include "mush.h"
  1034. X
  1035. Xmake_main_panel(choice_args, button_args)
  1036. Xchar **choice_args, **button_args;
  1037. X{
  1038. X    /* main panel stuff: */
  1039. X    panel_sw = panel_create(tool,
  1040. X    PANEL_HEIGHT, 80,
  1041. X    0);
  1042. X    main_panel = (Panel)panel_sw->ts_data;
  1043. X
  1044. X    quit_item = panel_create_item(main_panel, PANEL_CHOICE,
  1045. X    PANEL_ATTRIBUTE_LIST,         choice_args,
  1046. X    PANEL_ITEM_X,            4,
  1047. X    PANEL_ITEM_Y,            4,
  1048. X    PANEL_LABEL_IMAGE,
  1049. X        panel_button_image(main_panel, "Done", 6, fonts[LARGE]),
  1050. X    PANEL_MENU_TITLE_STRING,     "Done",
  1051. X    PANEL_CHOICE_STRINGS,         "Close to Icon",
  1052. X                    "Quit Tool",
  1053. X                    "Help",
  1054. X                    0,
  1055. X    PANEL_NOTIFY_PROC,         toolquit,
  1056. X    0);
  1057. X
  1058. X    help_item = panel_create_item(main_panel, PANEL_CHOICE,
  1059. X    PANEL_ATTRIBUTE_LIST,         choice_args,
  1060. X    PANEL_ITEM_X,            79,
  1061. X    PANEL_ITEM_Y,            4,
  1062. X    PANEL_LABEL_IMAGE,
  1063. X        panel_button_image(main_panel, "Help", 4, fonts[LARGE]),
  1064. X    PANEL_MENU_TITLE_STRING,     "Available Help",
  1065. X    PANEL_CHOICE_STRINGS,         "General",
  1066. X                    "Help with \"help\"",
  1067. X                    "The Mouse",
  1068. X                    "Windows",
  1069. X                    "Function Keys",
  1070. X                    "Message headers",
  1071. X                    "Message lists",
  1072. X                    0,
  1073. X    PANEL_NOTIFY_PROC,         do_help,
  1074. X    0);
  1075. X
  1076. X    read_item = panel_create_item(main_panel, PANEL_CHOICE,
  1077. X    PANEL_ATTRIBUTE_LIST,         choice_args,
  1078. X    PANEL_ITEM_X,            136,
  1079. X    PANEL_ITEM_Y,            4,
  1080. X    PANEL_LABEL_IMAGE,
  1081. X        panel_button_image(main_panel, "Next", 4, fonts[LARGE]),
  1082. X    PANEL_MENU_TITLE_STRING,     "Next Message",
  1083. X    PANEL_CHOICE_STRINGS,         "Read Next", "Help", 0,
  1084. X    PANEL_NOTIFY_PROC,         read_mail,
  1085. X    0);
  1086. X
  1087. X    respond_item = panel_create_item(main_panel, PANEL_CHOICE,
  1088. X    PANEL_ATTRIBUTE_LIST,         choice_args,
  1089. X    PANEL_ITEM_X,            193,
  1090. X    PANEL_ITEM_Y,            4,
  1091. X    PANEL_LABEL_IMAGE,
  1092. X        panel_button_image(main_panel, "Reply", 5, fonts[LARGE]),
  1093. X    PANEL_MENU_TITLE_STRING,     "Respond to Current Message",
  1094. X    PANEL_CHOICE_STRINGS,         "Sender Only",
  1095. X                    "Sender Only (include msg)",
  1096. X                    "All Recipients",
  1097. X                    "All Recipients (include msg)",
  1098. X                    "Help", 0,
  1099. X    PANEL_NOTIFY_PROC,         respond_mail,
  1100. X    0);
  1101. X
  1102. X    delete_item = panel_create_item(main_panel, PANEL_CHOICE,
  1103. X    PANEL_ATTRIBUTE_LIST,         choice_args,
  1104. X    PANEL_ITEM_X,            259,
  1105. X    PANEL_ITEM_Y,            4,
  1106. X    PANEL_LABEL_IMAGE,
  1107. X        panel_button_image(main_panel, "Delete", 6, fonts[LARGE]),
  1108. X    PANEL_MENU_TITLE_STRING,     "Delete/Undelete Messages",
  1109. X    PANEL_CHOICE_STRINGS,         "Delete current message",
  1110. X                    "Delete All Messages",
  1111. X                    "Undelete current message",
  1112. X                    "Undelete All Messages",
  1113. X                    "Delete message \"range\"",
  1114. X                    "Undelete message \"Range\"",
  1115. X                    "Help", 0,
  1116. X    PANEL_NOTIFY_PROC,         delete_mail,
  1117. X    0);
  1118. X
  1119. X    sort_item = panel_create_item(main_panel, PANEL_CHOICE,
  1120. X    PANEL_ATTRIBUTE_LIST,         choice_args,
  1121. X    PANEL_ITEM_X,            334,
  1122. X    PANEL_ITEM_Y,            4,
  1123. X    PANEL_LABEL_IMAGE,
  1124. X        panel_button_image(main_panel, "Sort", 4, fonts[LARGE]),
  1125. X    PANEL_MENU_TITLE_STRING,     "Sort Messages",
  1126. X    PANEL_CHOICE_STRINGS,         "By Date",
  1127. X                    "By Author",
  1128. X                    "By Subject",
  1129. X                    "By Subject (ignore Re:)",
  1130. X                    "By Status",
  1131. X                    "Help", 0,
  1132. X    PANEL_NOTIFY_PROC,         do_sort,
  1133. X    0);
  1134. X
  1135. X    option_item = panel_create_item(main_panel, PANEL_CHOICE,
  1136. X    PANEL_ATTRIBUTE_LIST,         choice_args,
  1137. X    PANEL_ITEM_X,            391,
  1138. X    PANEL_ITEM_Y,            4,
  1139. X    PANEL_LABEL_IMAGE,
  1140. X        panel_button_image(main_panel, "Opts", 4, fonts[LARGE]),
  1141. X    PANEL_MENU_TITLE_STRING,     "Mail Options",
  1142. X    PANEL_CHOICE_STRINGS,         "Set Options", "Function keys",
  1143. X                    "Help", 0,
  1144. X    PANEL_NOTIFY_PROC,         p_set_opts,
  1145. X    0);
  1146. X
  1147. X    alias_item = panel_create_item(main_panel, PANEL_CHOICE,
  1148. X    PANEL_ATTRIBUTE_LIST,         choice_args,
  1149. X    PANEL_ITEM_X,            448,
  1150. X    PANEL_ITEM_Y,            4,
  1151. X    PANEL_LABEL_IMAGE,
  1152. X        panel_button_image(main_panel, "Aliases", 7, fonts[LARGE]),
  1153. X    PANEL_MENU_TITLE_STRING,     "Mail Aliases",
  1154. X    PANEL_CHOICE_STRINGS,         "Current Aliases",
  1155. X                    "Add/Change alias",
  1156. X                    "Unalias", "Help", 0,
  1157. X    PANEL_NOTIFY_PROC,         p_set_opts,
  1158. X    0);
  1159. X
  1160. X    comp_item = panel_create_item(main_panel, PANEL_CHOICE,
  1161. X    PANEL_ATTRIBUTE_LIST,         choice_args,
  1162. X    PANEL_ITEM_X,            532,
  1163. X    PANEL_ITEM_Y,            4,
  1164. X    PANEL_LABEL_IMAGE,
  1165. X        panel_button_image(main_panel, "Compose", 8, fonts[LARGE]),
  1166. X    PANEL_MENU_TITLE_STRING,     "Compose a letter",
  1167. X    PANEL_CHOICE_STRINGS,         "Help", 0,
  1168. X    PANEL_NOTIFY_PROC,         do_compose,
  1169. X    0);
  1170. X
  1171. X    file_item = panel_create_item(main_panel, PANEL_TEXT,
  1172. X    PANEL_ATTRIBUTE_LIST,         choice_args,
  1173. X    PANEL_ITEM_X,            4,
  1174. X    PANEL_ITEM_Y,            30,
  1175. X    PANEL_LABEL_FONT,         fonts[DEFAULT],
  1176. X    PANEL_SHOW_MENU,        TRUE,
  1177. X    PANEL_LABEL_STRING,         "filename:",
  1178. X    PANEL_MENU_CHOICE_STRINGS,    "Save message without message header",0,
  1179. X    PANEL_VALUE_DISPLAY_LENGTH,     35,
  1180. X    PANEL_NOTIFY_STRING,         "\n\r",
  1181. X    PANEL_NOTIFY_PROC,         file_dir,
  1182. X    0);
  1183. X
  1184. X    input_item = panel_create_item(main_panel, PANEL_TEXT,
  1185. X    PANEL_ATTRIBUTE_LIST,         choice_args,
  1186. X    PANEL_ITEM_X,            373,
  1187. X    PANEL_ITEM_Y,            30,
  1188. X    PANEL_SHOW_ITEM,         FALSE,
  1189. X    PANEL_SHOW_MENU,         TRUE,
  1190. X    PANEL_LABEL_FONT,         fonts[DEFAULT],
  1191. X    PANEL_VALUE_DISPLAY_LENGTH,     20,
  1192. X    PANEL_NOTIFY_STRING,         "\n\r",
  1193. X    PANEL_NOTIFY_PROC,         text_done,
  1194. X    0);
  1195. X
  1196. X    print_item = panel_create_item(main_panel, PANEL_CHOICE,
  1197. X    PANEL_ATTRIBUTE_LIST,         choice_args,
  1198. X    PANEL_ITEM_X,            4,
  1199. X    PANEL_ITEM_Y,            50,
  1200. X    PANEL_LABEL_IMAGE,
  1201. X        panel_button_image(main_panel, "Printer", 7, fonts[LARGE]),
  1202. X    PANEL_MENU_TITLE_STRING,     "Printing Messages",
  1203. X    PANEL_CHOICE_STRINGS,         "Help", 0,
  1204. X    PANEL_NOTIFY_PROC,         do_lpr,
  1205. X    0);
  1206. X
  1207. X    folder_item = panel_create_item(main_panel, PANEL_CHOICE,
  1208. X    PANEL_ATTRIBUTE_LIST,         choice_args,
  1209. X    PANEL_ITEM_X,            88,
  1210. X    PANEL_ITEM_Y,            50,
  1211. X    PANEL_LABEL_IMAGE,
  1212. X        panel_button_image(main_panel, "folder", 6, fonts[LARGE]),
  1213. X    PANEL_MENU_TITLE_STRING,     "Change folder",
  1214. X    PANEL_CHOICE_STRINGS,         "System Mailbox",
  1215. X                    "Main Mailbox",
  1216. X                    "Last Accessed Folder",
  1217. X                    0,
  1218. X    PANEL_NOTIFY_PROC,         do_file_dir,
  1219. X    0);
  1220. X
  1221. X    add_folder_to_menu(folder_item, 3);
  1222. X
  1223. X    save_item = panel_create_item(main_panel, PANEL_CHOICE,
  1224. X    PANEL_ATTRIBUTE_LIST,         choice_args,
  1225. X    PANEL_ITEM_X,            163,
  1226. X    PANEL_ITEM_Y,            50,
  1227. X    PANEL_LABEL_IMAGE,
  1228. X        panel_button_image(main_panel, "Save", 4, fonts[LARGE]),
  1229. X    PANEL_MENU_TITLE_STRING,     "Save messages",
  1230. X    PANEL_CHOICE_STRINGS,         "Save in ~/mbox",
  1231. X                    "Save message \"range\"",
  1232. X                    0,
  1233. X    PANEL_NOTIFY_PROC,         do_file_dir,
  1234. X    0);
  1235. X
  1236. X    add_folder_to_menu(save_item, 2);
  1237. X
  1238. X    cd_item = panel_create_item(main_panel, PANEL_CHOICE,
  1239. X    PANEL_ATTRIBUTE_LIST,         choice_args,
  1240. X    PANEL_ITEM_X,            220,
  1241. X    PANEL_ITEM_Y,            50,
  1242. X    PANEL_LABEL_IMAGE,
  1243. X        panel_button_image(main_panel, "chdir", 5, fonts[LARGE]),
  1244. X    PANEL_MENU_TITLE_STRING,     "Change Working Directory",
  1245. X    PANEL_CHOICE_STRINGS,         "Print Current directory",
  1246. X                    "HOME directory",
  1247. X                    "Private Mail directory.",
  1248. X                    "Help", 0,
  1249. X    PANEL_NOTIFY_PROC,         do_file_dir,
  1250. X    0);
  1251. X
  1252. X    update_item = panel_create_item(main_panel, PANEL_CHOICE,
  1253. X    PANEL_ATTRIBUTE_LIST,         choice_args,
  1254. X    PANEL_ITEM_X,            286,
  1255. X    PANEL_ITEM_Y,            50,
  1256. X    PANEL_LABEL_IMAGE,
  1257. X        panel_button_image(main_panel, "Update", 6, fonts[LARGE]),
  1258. X    PANEL_MENU_TITLE_STRING,     "Updating folders",
  1259. X    PANEL_CHOICE_STRINGS,         "Help", 0,
  1260. X    PANEL_NOTIFY_PROC,         do_update,
  1261. X    0);
  1262. X
  1263. X    send_item = panel_create_item(main_panel, PANEL_CHOICE,
  1264. X    PANEL_ATTRIBUTE_LIST,         choice_args,
  1265. X    PANEL_ITEM_X,            361,
  1266. X    PANEL_ITEM_Y,            50,
  1267. X    PANEL_SHOW_ITEM,         FALSE,
  1268. X    PANEL_LABEL_IMAGE,
  1269. X        panel_button_image(main_panel, "Send", 6, fonts[LARGE]),
  1270. X    PANEL_MENU_TITLE_STRING,     "Send Letter",
  1271. X    PANEL_CHOICE_STRINGS,         "Help", 0,
  1272. X    PANEL_NOTIFY_PROC,         do_send,
  1273. X    0);
  1274. X
  1275. X    edit_item = panel_create_item(main_panel, PANEL_CHOICE,
  1276. X    PANEL_ATTRIBUTE_LIST,         choice_args,
  1277. X    PANEL_ITEM_X,            436,
  1278. X    PANEL_ITEM_Y,            50,
  1279. X    PANEL_SHOW_ITEM,         FALSE,
  1280. X    PANEL_LABEL_IMAGE,
  1281. X        panel_button_image(main_panel, "Editor", 4, fonts[LARGE]),
  1282. X    PANEL_MENU_TITLE_STRING,     "Editing",
  1283. X    PANEL_CHOICE_STRINGS,         "Help", 0,
  1284. X    PANEL_NOTIFY_PROC,         do_edit,
  1285. X    0);
  1286. X
  1287. X    abort_item = panel_create_item(main_panel, PANEL_BUTTON,
  1288. X    PANEL_ATTRIBUTE_LIST,         button_args,
  1289. X    PANEL_ITEM_X,            511,
  1290. X    PANEL_ITEM_Y,            50,
  1291. X    PANEL_SHOW_ITEM,         FALSE,
  1292. X    PANEL_LABEL_IMAGE,
  1293. X        panel_button_image(main_panel, "Abort", 5, fonts[LARGE]),
  1294. X    PANEL_NOTIFY_PROC,         abort_mail,
  1295. X    0);
  1296. X
  1297. X    font_item = panel_create_item(main_panel, PANEL_CHOICE,
  1298. X    PANEL_ATTRIBUTE_LIST,         choice_args,
  1299. X    PANEL_ITEM_X,            577,
  1300. X    PANEL_ITEM_Y,            50,
  1301. X    PANEL_LABEL_IMAGE,
  1302. X        panel_button_image(main_panel, "Fonts", 5, fonts[LARGE]),
  1303. X    PANEL_MENU_TITLE_STRING,     "Fonts",
  1304. X    PANEL_SHOW_MENU_MARK,         TRUE,
  1305. X    PANEL_CHOICE_FONTS,         fonts[0], fonts[1], fonts[2], 0,
  1306. X    PANEL_CHOICE_STRINGS,         "Default", "Small", "Large", 0,
  1307. X    PANEL_NOTIFY_PROC,         change_font,
  1308. X    0);
  1309. X}
  1310. X
  1311. X/*
  1312. X * Open the user's mail folder (either user set or default path) and find all
  1313. X * the files (assumed to be mail folders) and add them to the menu list of
  1314. X * folders to use.
  1315. X */
  1316. Xadd_folder_to_menu(item, n)
  1317. Xstruct panel_item *item;
  1318. Xregister int       n;
  1319. X{
  1320. X    register FILE     *pp = NULL_FILE;
  1321. X    register char     *p = do_set(set_options, "folder");
  1322. X    register char    *tmp = NULL;
  1323. X    int            x = 0;
  1324. X    char         buf[128], path[128];
  1325. X
  1326. X    if (p) {
  1327. X    tmp = getpath(p, &x);
  1328. X    if (x == -1) {
  1329. X        if (errno != ENOENT)
  1330. X        print("%s: %s\n", p, tmp);
  1331. X        tmp = NULL;
  1332. X    }
  1333. X    }
  1334. X    if (p = tmp) {
  1335. X    p = sprintf(buf, "%s %s", LS_COMMAND, p);
  1336. X    if (!(pp = popen(buf, "r")))
  1337. X        error(buf);
  1338. X    else {
  1339. X        *path = '+';
  1340. X        while (fgets(path+1, 128, pp)) {
  1341. X        struct stat s_buf;
  1342. X        if (p = index(path+1, '\n'))
  1343. X            *p = 0;
  1344. X        (void) sprintf(buf, "%s/%s", tmp, path+1);
  1345. X        if (stat(buf, &s_buf) || s_buf.st_mode & S_IFDIR)
  1346. X            continue;
  1347. X        panel_set(item, PANEL_CHOICE_STRING, n++, path, 0);
  1348. X        }
  1349. X    }
  1350. X    }
  1351. X    panel_set(item, PANEL_CHOICE_STRING, n, "Help", 0);
  1352. X}
  1353. END_OF_FILE
  1354. if test 9355 -ne `wc -c <'main_panel.c'`; then
  1355.     echo shar: \"'main_panel.c'\" unpacked with wrong size!
  1356. fi
  1357. # end of 'main_panel.c'
  1358. fi
  1359. if test -f 'rite.c' -a "${1}" != "-c" ; then 
  1360.   echo shar: Will not clobber existing file \"'rite.c'\"
  1361. else
  1362. echo shar: Extracting \"'rite.c'\" \(4613 characters\)
  1363. sed "s/^X//" >'rite.c' <<'END_OF_FILE'
  1364. X/* rite.c    (c) copyright 1986 (Dan Heller) */
  1365. X
  1366. X#include "mush.h"
  1367. X
  1368. X#define LASTLINE       (msg_rect.r_height - l_height(LARGE)-5)
  1369. X
  1370. Xstatic char *_unctrl[] = {
  1371. X    "^@", "^A", "^B", "^C", "^D", "^E", "^F", "^G", "^H", "^I", "^J", "^K",
  1372. X    "^L", "^M", "^N", "^O", "^P", "^Q", "^R", "^S", "^T", "^U", "^V", "^W",
  1373. X    "^X", "^Y", "^Z", "^[", "^\\", "^]", "^~", "^_",
  1374. X    " ", "!", "\"", "#", "$",  "%", "&", "'", "(", ")", "*", "+", ",", "-",
  1375. X    ".", "/", "0",  "1", "2",  "3", "4", "5", "6", "7", "8", "9", ":", ";",
  1376. X    "<", "=", ">",  "?", "@",  "A", "B", "C", "D", "E", "F", "G", "H", "I",
  1377. X    "J", "K", "L",  "M", "N",  "O", "P", "Q", "R", "S", "T", "U", "V", "W",
  1378. X    "X", "Y", "Z",  "[", "\\", "]", "^", "_", "`", "a", "b", "c", "d", "e",
  1379. X    "f", "g", "h",  "i", "j",  "k", "l", "m", "n", "o", "p", "q", "r", "s",
  1380. X    "t", "u", "v",  "w", "x",  "y", "z", "{", "|", "}", "~", "^?"
  1381. X};
  1382. X
  1383. Xstatic char String[BUFSIZ];
  1384. Xstatic int count, backchars, save_orig_x;
  1385. X
  1386. Xchar *
  1387. Xrite(c)
  1388. Xregister char c;
  1389. X{
  1390. X    static int literal_next;
  1391. X
  1392. X    if (c == ltchars.t_lnextc || literal_next) {
  1393. X    if (literal_next)
  1394. X        Addch(c);
  1395. X    else /* don't call Addch to prevent cursor from advancing */
  1396. X        pw_char(msg_win, txt.x, txt.y, PIX_SRC, fonts[curfont], '^');
  1397. X    literal_next = !literal_next;
  1398. X    return NULL;
  1399. X    }
  1400. X    literal_next = 0;
  1401. X    if (c == _tty.sg_erase) {
  1402. X    if (count)
  1403. X        backspace(), String[count--] = 0;
  1404. X    } else if (c == _tty.sg_kill) {
  1405. X    if (count) {
  1406. X        Clrtoeol(msg_win, txt.x = save_orig_x, txt.y,curfont);
  1407. X        String[count=0] = 0;
  1408. X    }
  1409. X    } else if (c == ltchars.t_werasc)
  1410. X    while (count) {
  1411. X        backspace();
  1412. X        String[count--] = 0;
  1413. X        if (!count || (String[count-1]==' ' && !isspace(String[count])))
  1414. X        break;
  1415. X    }
  1416. X    else if (c == '\n' || c == '\r' || c == 13) {
  1417. X    String[count] = 0;
  1418. X    if ((txt.y += l_height(curfont)) >= LASTLINE && !getting_opts)
  1419. X        scroll_win(1);
  1420. X    /* else Clrtoeol(msg_win, txt.x, txt.y, curfont); */
  1421. X    count = 0, txt.x = 5;
  1422. X    return String;
  1423. X    } else if (c == 12) {
  1424. X    if (ison(glob_flags, IS_GETTING))
  1425. X        Addch(c);
  1426. X    else do_clear();
  1427. X    } else if (count == BUFSIZ-1)
  1428. X    print("Text too long for String!"), count--;
  1429. X    else if (c == '\t')
  1430. X    do Addch(' ');
  1431. X    while (count % 8 && count < BUFSIZ);
  1432. X    else
  1433. X    Addch(c);
  1434. X    return NULL;
  1435. X}
  1436. X
  1437. Xbackspace()
  1438. X{
  1439. X    if (backchars) {
  1440. X    pw_text(msg_win, save_orig_x, txt.y, PIX_SRC, fonts[curfont],
  1441. X        &String[--backchars]);
  1442. X    Clrtoeol(msg_win, msg_rect.r_width-10-l_width(curfont), txt.y, curfont);
  1443. X    } else if ((txt.x -= l_width(curfont)) >= 5)
  1444. X    pw_char(msg_win, txt.x, txt.y, PIX_SRC, fonts[curfont], ' ');
  1445. X    else
  1446. X    txt.x = 5;
  1447. X}
  1448. X
  1449. Xstatic
  1450. XAddch(c)
  1451. Xregister char c;
  1452. X{
  1453. X    if (!count)
  1454. X    save_orig_x = txt.x, bzero(String, BUFSIZ);
  1455. X    if (c > 31 && c != 127)
  1456. X    String[count++] = c;
  1457. X    else {
  1458. X    Addch('^');
  1459. X    Addch(_unctrl[c][1]);
  1460. X    return;
  1461. X    }
  1462. X    pw_char(msg_win, txt.x, txt.y, PIX_SRC, fonts[curfont], c);
  1463. X    if ((txt.x += l_width(curfont)) <= msg_rect.r_width-5-l_width(curfont))
  1464. X    return;
  1465. X    if (getting_opts) {
  1466. X    pw_text(msg_win, save_orig_x, txt.y, PIX_SRC, fonts[curfont],
  1467. X        &String[++backchars]);
  1468. X    txt.x -= l_width(curfont);
  1469. X    pw_char(msg_win, txt.x, txt.y, PIX_SRC, fonts[curfont], ' ');
  1470. X    } else {
  1471. X    txt.x = 5;
  1472. X    if ((txt.y += l_height(curfont)) >= LASTLINE)
  1473. X        scroll_win(1);
  1474. X    }
  1475. X}
  1476. X
  1477. XAddstr(s)
  1478. Xregister char *s;
  1479. X{
  1480. X    char buf[BUFSIZ];
  1481. X    register int cnt = 0, max_len;
  1482. X    register char *p = buf, newline = 0;
  1483. X
  1484. X    max_len = (msg_rect.r_width - 10) / l_width(curfont) + 1;
  1485. X
  1486. X    while ((*p = *s++) && *p != '\n' && cnt < max_len)
  1487. X    if (*p == '\t')
  1488. X        do *p++ = ' ';
  1489. X        while (++cnt % 8);
  1490. X    else p++, cnt++;
  1491. X    *p = 0;
  1492. X
  1493. X    if (*--s)
  1494. X    newline = *s, *s = 0; /* newline may or may not be a '\n' */
  1495. X    else
  1496. X    s = 0;
  1497. X
  1498. X    if (*buf) {
  1499. X    if (msg_pix) {
  1500. X        struct pr_prpos pixr;
  1501. X        pixr.pr = msg_pix;
  1502. X        pixr.pos = txt;
  1503. X        pf_text(pixr, PIX_SRC, fonts[curfont], buf);
  1504. X    } else
  1505. X        pw_text(msg_win, txt.x, txt.y, PIX_SRC, fonts[curfont], buf);
  1506. X    txt.x += cnt * l_width(curfont);
  1507. X    }
  1508. X    if (newline) {
  1509. X    if (newline != '\n')
  1510. X        *s = newline;
  1511. X    if ((txt.y += l_height(curfont)) >= LASTLINE && !msg_pix)
  1512. X        scroll_win(1);
  1513. X    txt.x = 5;
  1514. X    if (newline == '\n' && !*++s)
  1515. X        return;
  1516. X    Addstr(s);
  1517. X    }
  1518. X}
  1519. X
  1520. Xtool_more(p)
  1521. Xregister char *p;
  1522. X{
  1523. X    int percent;
  1524. X    /* we are typing -- scrool the window */
  1525. X    if (!msg_pix) {
  1526. X    scroll_win(1);
  1527. X    return;
  1528. X    }
  1529. X    if (p)
  1530. X    print(p);
  1531. X    else {
  1532. X    if ((percent = (still_more * 100) / msg_pix->pr_size.y) >= 100)
  1533. X        print( "--End of Message %d--", current_msg+1);
  1534. X    else
  1535. X        print("--Message %d--(%d%%)", current_msg+1, percent);
  1536. X    if (ison(glob_flags, IS_GETTING))
  1537. X        print_more(" ('q' returns to type-in mode)");
  1538. X    }
  1539. X}
  1540. END_OF_FILE
  1541. if test 4613 -ne `wc -c <'rite.c'`; then
  1542.     echo shar: \"'rite.c'\" unpacked with wrong size!
  1543. fi
  1544. # end of 'rite.c'
  1545. fi
  1546. if test -f 'sort.c' -a "${1}" != "-c" ; then 
  1547.   echo shar: Will not clobber existing file \"'sort.c'\"
  1548. else
  1549. echo shar: Extracting \"'sort.c'\" \(5125 characters\)
  1550. sed "s/^X//" >'sort.c' <<'END_OF_FILE'
  1551. X/* signals.c 1.1    (c) copyright 1986 (Dan Heller) */
  1552. X
  1553. X#include "mush.h"
  1554. X/* #define MYQSORT */
  1555. X
  1556. Xstatic int order;
  1557. Xstatic jmp_buf sortbuf;
  1558. X
  1559. Xsort(argc, argv, list)
  1560. Xregister int argc;
  1561. Xregister char *argv[], list[];
  1562. X{
  1563. X    int status_cmp(), author_cmp(), date_cmp(), subject_cmp(), subj_with_re();
  1564. X    int (*oldint)(), (*oldquit)();
  1565. X    int (*how)() = status_cmp;
  1566. X    int n, offset = -1, range = 0;
  1567. X
  1568. X    order = 1;
  1569. X
  1570. X    while (argc && *++argv) {
  1571. X    n = 0;
  1572. X    while (argv[0][n])
  1573. X        switch(argv[0][n++]) {
  1574. X        case '-': order = -1;
  1575. X        when 'd': how = date_cmp;
  1576. X        when 'a': how = author_cmp;
  1577. X        when 's': how = subject_cmp;
  1578. X        when 'R': how = subj_with_re;
  1579. X        when 'S': how = status_cmp;
  1580. X        otherwise: return help(0, "sort_help", cmd_help);
  1581. X        }
  1582. X    }
  1583. X    if (msg_cnt <= 1) {
  1584. X    print("Not enough messages to sort.\n");
  1585. X    return -1;
  1586. X    }
  1587. X    on_intr();
  1588. X
  1589. X    if (list && ison(glob_flags, IS_PIPE)) {
  1590. X    for (n = 0; n < msg_cnt; n++)
  1591. X        if (msg_bit(list, n)) {
  1592. X        if (offset < 0)
  1593. X            offset = n;
  1594. X        range++;
  1595. X        } else if (offset >= 0)
  1596. X        break;
  1597. X    } else
  1598. X    offset = 0, range = msg_cnt;
  1599. X
  1600. X    if (range < 2)
  1601. X    print("Range not broad enough to sort anything\n");
  1602. X    else {
  1603. X    Debug("Sorting %d messages starting at message %d\n", range, offset+1);
  1604. X
  1605. X    if (setjmp(sortbuf) == 0)
  1606. X        qsort((char *)&msg[offset], range, sizeof (struct msg), how);
  1607. X    else
  1608. X        print("WARNING: Sorting interrupted: unpredictable order.\n");
  1609. X    turnon(glob_flags, DO_UPDATE);
  1610. X    }
  1611. X    off_intr();
  1612. X    return -1;
  1613. X}
  1614. X
  1615. X#ifdef MYQSORT
  1616. Xqsort(base, len, siz, compar)
  1617. Xregister struct msg *base;
  1618. Xint (*compar)();
  1619. X{
  1620. X     register int i, swapping;
  1621. X     struct msg temp;
  1622. X
  1623. X     do  {
  1624. X     swapping = 0;
  1625. X     for (i = 0; i < len-1; ++i) {
  1626. X         if (compar(base+i, base+i+1) > 0) {
  1627. X         temp = base[i];
  1628. X         base[i] = base[i+1];
  1629. X         base[i+1] = temp;
  1630. X         swapping = 1;
  1631. X         }
  1632. X     }
  1633. X     } while (swapping);
  1634. X}
  1635. X#endif MYSORT
  1636. X
  1637. Xstatus_cmp(msg1, msg2)
  1638. Xregister struct msg *msg1, *msg2;
  1639. X{
  1640. X    if (ison(glob_flags, WAS_INTR))
  1641. X    longjmp(sortbuf, 1);
  1642. X    if (msg1 < msg || msg2 < msg) {
  1643. X    wprint("sort botch trying to sort %d and %d\n", msg1-msg, msg2-msg);
  1644. X    return 0;
  1645. X    }
  1646. X    if (msg1->m_flags == msg2->m_flags)
  1647. X        return 0;
  1648. X    if (ison(msg1->m_flags, DELETE) && isoff(msg2->m_flags, DELETE))
  1649. X    return order;
  1650. X    if (isoff(msg1->m_flags, DELETE) && ison(msg2->m_flags, DELETE))
  1651. X    return -order;
  1652. X    if (isoff(msg1->m_flags, OLD) && ison(msg2->m_flags, OLD))
  1653. X    return -order;
  1654. X    if (ison(msg1->m_flags, OLD) && isoff(msg2->m_flags, OLD))
  1655. X    return order;
  1656. X    if (ison(msg1->m_flags, UNREAD) && isoff(msg2->m_flags, UNREAD))
  1657. X    return -order;
  1658. X    if (isoff(msg1->m_flags, UNREAD) && ison(msg2->m_flags, UNREAD))
  1659. X    return order;
  1660. X    if (ison(msg1->m_flags,PRESERVE) && isoff(msg2->m_flags,PRESERVE))
  1661. X    return -order;
  1662. X    if (isoff(msg1->m_flags,PRESERVE) && ison(msg2->m_flags,PRESERVE))
  1663. X    return order;
  1664. X
  1665. X    return order;
  1666. X}
  1667. X
  1668. Xauthor_cmp(msg1, msg2)
  1669. Xregister struct msg *msg1, *msg2;
  1670. X{
  1671. X    char buf1[BUFSIZ], buf2[BUFSIZ];
  1672. X
  1673. X    if (ison(glob_flags, WAS_INTR))
  1674. X    longjmp(sortbuf, 1);
  1675. X    if (msg1 < msg || msg2 < msg) {
  1676. X    wprint("sort botch trying to sort %d and %d\n", msg1-msg, msg2-msg);
  1677. X    return 0;
  1678. X    }
  1679. X    (void) reply_to(msg1 - msg, 0, buf1); /* "0" for "author only" */
  1680. X    (void) reply_to(msg2 - msg, 0, buf2);
  1681. X    Debug("author: msg %d: %s, msg %d: %s\n", msg1-msg, buf1, msg2-msg, buf2);
  1682. X    return strcmp(buf1, buf2) * order;
  1683. X}
  1684. X
  1685. X/*
  1686. X * compare subject strings from two messages.
  1687. X * If Re is appended, so be it -- if user wants to ignore Re: use 'R' flag.
  1688. X */
  1689. Xsubj_with_re(msg1, msg2)
  1690. Xregister struct msg *msg1, *msg2;
  1691. X{
  1692. X    char buf1[256], buf2[256];
  1693. X
  1694. X    if (ison(glob_flags, WAS_INTR))
  1695. X    longjmp(sortbuf, 1);
  1696. X    if (msg1 < msg || msg2 < msg) {
  1697. X    wprint("sort botch trying to sort %d and %d\n", msg1-msg, msg2-msg);
  1698. X    return 0;
  1699. X    }
  1700. X    (void) subject_to(msg1 - msg, buf1);
  1701. X    (void) subject_to(msg2 - msg, buf2);
  1702. X    Debug("subjects: (%d): \"%s\" (%d): \"%s\"\n", msg1-msg,buf1,msg2-msg,buf2);
  1703. X    return strcmp(buf1, buf2) * order;
  1704. X}
  1705. X
  1706. X/*
  1707. X * Subject comparison ignoring Re:  subject_to() appends an Re: if there is
  1708. X * any subject whatsoever.  If so, skip 4 chars.  If not, set to ""
  1709. X */
  1710. Xsubject_cmp(msg1, msg2)
  1711. Xregister struct msg *msg1, *msg2;
  1712. X{
  1713. X    char buf1[256], buf2[256], *p1, *p2;
  1714. X
  1715. X    if (ison(glob_flags, WAS_INTR))
  1716. X    longjmp(sortbuf, 1);
  1717. X    if (msg1 < msg || msg2 < msg) {
  1718. X    wprint("sort botch trying to sort %d and %d\n", msg1-msg, msg2-msg);
  1719. X    return 0;
  1720. X    }
  1721. X    if (p1 = subject_to(msg1 - msg, buf1))
  1722. X    p1 += 4;
  1723. X    else
  1724. X    p1 = "";
  1725. X    if (p2 = subject_to(msg2 - msg, buf2))
  1726. X    p2 += 4;
  1727. X    else
  1728. X    p2 = "";
  1729. X    Debug("subjects: (%d): \"%s\" (%d): \"%s\"\n", msg1-msg, p1, msg2-msg, p2);
  1730. X    return strcmp(p1, p2) * order;
  1731. X}
  1732. X
  1733. Xdate_cmp(msg1, msg2)
  1734. Xregister struct msg *msg1, *msg2;
  1735. X{
  1736. X    char buf1[11], buf2[11];
  1737. X
  1738. X    if (ison(glob_flags, WAS_INTR))
  1739. X    longjmp(sortbuf, 1);
  1740. X    if (msg1 < msg || msg2 < msg) {
  1741. X    wprint("sort botch trying to sort %d and %d\n", msg1-msg, msg2-msg);
  1742. X    return 0;
  1743. X    }
  1744. X    (void) strcpy(buf1, msg_date(msg1-msg));
  1745. X    (void) strcpy(buf2, msg_date(msg2-msg));
  1746. X    Debug("dates: msg %d: %s, msg %d: %s\n", msg1-msg, buf1, msg2-msg, buf2);
  1747. X    return strcmp(buf1, buf2) * order;
  1748. X}
  1749. END_OF_FILE
  1750. if test 5125 -ne `wc -c <'sort.c'`; then
  1751.     echo shar: \"'sort.c'\" unpacked with wrong size!
  1752. fi
  1753. # end of 'sort.c'
  1754. fi
  1755. echo shar: End of archive 2 \(of 12\).
  1756. cp /dev/null ark2isdone
  1757. MISSING=""
  1758. for I in 1 2 3 4 5 6 7 8 9 10 11 12 ; do
  1759.     if test ! -f ark${I}isdone ; then
  1760.     MISSING="${MISSING} ${I}"
  1761.     fi
  1762. done
  1763. if test "${MISSING}" = "" ; then
  1764.     echo You have unpacked all 12 archives.
  1765.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1766. else
  1767.     echo You still need to unpack the following archives:
  1768.     echo "        " ${MISSING}
  1769. fi
  1770. ##  End of shell archive.
  1771. exit 0
  1772.